package com.yiwyn.demo.utils.modify;

import com.yiwyn.demo.utils.modify.anno.modify.ModifyType;
import com.yiwyn.demo.utils.modify.entity.ModifyEntity;
import com.yiwyn.demo.utils.modify.handle.ModifyAnnoHandleRouter;
import com.yiwyn.demo.utils.modify.handle.event.base.BaseTypeEvent;
import com.yiwyn.demo.utils.modify.handle.router.base.BaseModifyFieldRoute;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;


public class ModifyComponent {


    private static final Map<Class<?>, BaseTypeEvent<?>> baseTypeEventMap = new HashMap<>();


    public static <T> ModifyEntity record(T oldObject, T newObject) throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {

        Class<?> clazz = oldObject.getClass();
        ModifyType modifyTypeAnnotation = clazz.getAnnotation(ModifyType.class);
        if (modifyTypeAnnotation == null) {
            return null;
        }

        Class<? extends BaseTypeEvent> typeEventClazz = modifyTypeAnnotation.typeEventClazz();

        BaseTypeEvent<?> baseTypeEvent = baseTypeEventMap.computeIfAbsent(typeEventClazz, aClass -> {
            // 获取类事件
            try {
                return typeEventClazz.newInstance();
            } catch (Exception ignored) {
            }
            // 高版本java使用以下 「jdk9 将 newInstance标记为过期了」
            // BaseTypeEvent<?> baseTypeEvent = modifyTypeAnnotation.typeEventClazz().getDeclaredConstructor().newInstance();
            return null;
        });

        ModifyEntity modifyEntity = new ModifyEntity();
        modifyEntity.setModifyType(modifyTypeAnnotation.value());
        ArrayList<ModifyEntity.ModifyItem> modifyItems = new ArrayList<>();
        modifyEntity.setModifyItems(modifyItems);

        Field[] declaredFields = clazz.getDeclaredFields();

        for (Field field : declaredFields) {


            Annotation[] annotations = field.getAnnotations();
            for (Annotation annotation : annotations) {

                Class<? extends Annotation> annotationClazz = annotation.annotationType();
                if (!ModifyAnnoHandleRouter.containsRoute(annotationClazz)) {
                    continue;
                }

                field.setAccessible(true);

                // 获取新老值并进行对比，若相同则跳过
                Object oldObj = field.get(oldObject);
                Object newObj = field.get(newObject);

                if (Objects.equals(oldObj, newObj)) {
                    continue;
                }

                ModifyEntity.ModifyItem item = new ModifyEntity.ModifyItem();

                item.setOldValue(oldObj);
                item.setNewValue(newObj);

                // 匹配处理方法
                BaseModifyFieldRoute modifyFieldRoute = ModifyAnnoHandleRouter.getModifyFieldRoute(annotationClazz);
                // 加工item对象
                modifyFieldRoute.processField(field, item, baseTypeEvent);

                // 添加对变更字段列表中
                modifyItems.add(item);
            }
        }
        return modifyEntity;
    }

}
